package com.sgcc.pda.ssal.mqtt.proxy.client;

import android.util.Log;

import com.hzwq.codec.encrypt.EncryptHandler;
import com.hzwq.codec.handler.DefaultErrorHandler;
import com.hzwq.codec.handler.SSALContentBizAdapterHandler;
import com.hzwq.codec.handler.SSALErrorHandler;
import com.hzwq.codec.protocol.SSALDecoder;
import com.sgcc.pda.baselibrary.utils.LogUtil;
import com.sgcc.pda.ssal.mqtt.MQTTManager;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

/**
 * Created by cj on 2020/1/10.
 * 问题：无法在application中第一时间连接，因为这个时候还不知道server的ip
 * 解决：主应用在进入主界面时发送广播，接收到广播后开始连接。
 * 极速版不需要这个机制。
 */
public class MqttProxyClient {

    public static boolean isConnect = false;
    private static final String TAG = "mqtt";
    private static SocketChannel socketChannel;

    public static void connect(String ip, int port) {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        Bootstrap bootstrap = new Bootstrap();

        bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                //保持连接
                .option(ChannelOption.SO_KEEPALIVE, true)
                //有数据立即发送
                .option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        pipeline.addLast("ssalDecoder", new SSALDecoder(new EncryptHandler()));
                        pipeline.addLast("errorHandler", new SSALErrorHandler(new DefaultErrorHandler()));
                        pipeline.addLast("bizHandler", new SSALContentBizAdapterHandler());
                        pipeline.addLast("mqttClientHandler", new MqttClientHandler());
                    }
                });

        // 进行连接
        try {
            ChannelFuture future = bootstrap.connect(ip, port).sync();
//            ChannelFuture future = bootstrap.connect("192.168.15.68", 9003).sync();
            // 判断是否连接成功
            if (future.isSuccess()) {
                // 得到管道，便于通信
                socketChannel = (SocketChannel) future.channel();
                isConnect = true;
                LogUtil.e(TAG, "代理客户端连接网关成功...");
            } else {
                LogUtil.e(TAG, "代理客户端连接网关失败...");
            }
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
            isConnect = false;
            Log.e(TAG, "connect: " + e.getMessage());
        } finally {
            //优雅地退出，释放相关资源
            eventLoopGroup.shutdownGracefully();
            isConnect = false;
            LogUtil.e(TAG, "代理客户端关闭连接...");
            //paho客户端需要同步关闭
            MQTTManager.getInstance().disConnect();
        }
    }

    public static void sendMessage(Object msg) {
        if (socketChannel != null) {

            LogUtil.e(TAG, "socketChannel isActive： " + socketChannel.isActive());

            if (socketChannel.isWritable()) {
                socketChannel.writeAndFlush(msg);
                LogUtil.e(TAG, "代理客户端写出去消息");
            } else {
                LogUtil.e(TAG, "RejectedExecutionException:  socketChannel不可写");
            }

        } else {
            LogUtil.e(TAG, "代理客户端channel为空，无法写出消息");
        }
    }

    public static void closeConnection() {
        if (socketChannel != null) {
            try {
               socketChannel.close().sync();
                LogUtil.e(TAG, "代理客户端主动关闭");
            } catch (Exception e) {
                e.printStackTrace();
                LogUtil.e(TAG, "关闭exception");
            }

        } else {
            LogUtil.e(TAG, "代理客户端channel为空，无法关闭");
        }

    }
}
